<?php
// +----------------------------------------------------------------------
// | 有小象汇 自研正版源码 赋能开发者
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 http://www.uxphp.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 有小象汇并不是自由软件，未经许可不能去掉有小象汇相关版权
// +----------------------------------------------------------------------
// | Author:  有小象汇
// +----------------------------------------------------------------------
namespace app\services\car;

use app\dao\car\CarOrderRefundDao;
use app\model\car\CarOrder;
use app\model\car\CarOrderRefund;
use app\services\BaseServices;
use app\services\pay\PayServices;
use app\services\user\UserMoneyServices;
use app\services\user\UserServices;
use crmeb\exceptions\AdminException;
use think\exception\ValidateException;
use think\facade\Db;
use crmeb\services\app\MiniProgramService;
use crmeb\services\pay\Pay;
class CarOrderRefundServices extends BaseServices
{
    public function __construct(CarOrderRefundDao $dao)
    {
        $this->dao = $dao;
    }

    /**
     * 退款操作
     * @param $order
     * @param array $refundData
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function payOrderRefund($order, array $refundData)
    {
        return $this->transaction(function () use ($order,$refundData){
            $is_occupy = Db::name('car_occupy_time')->where(['order_id'=>$order['id'],'is_del'=>0])->select()->toArray();
            //回库存
            if ($is_occupy){
                foreach ($is_occupy as $val){ // 取消这订单下的所有库存占用时间
                    Db::name('car_occupy_time')->update(['id'=>$val['id'],'is_del'=>1,'remarks'=>"取消订单"]);
                }
            }
            //退金额
            if ($refundData['price']>0){
                if (!isset($refundData['refund_id']) || !$refundData['refund_id']){
                    mt_srand();
                    $refundData['refund_id'] = $order['order_no'].rand(100,900);
                    $refundOrder = $order;
                }
                switch ($refundOrder['pay_type']){
                    case PayServices::WEIXIN_PAY:
                        $no = $refundOrder['out_trade_no'];
                        $refundData['type'] = 'trade_no';
                        $refundData['pay_price'] = $order['price'];
                        $refundData['refund_price'] = $refundData['price'];
//                        if (sys_config('pay_wechat_type')) {//这里是v3版本的退款,需要去202账户弄到V3支付密钥,支付平台证书编号,才可使用 2024年3月9日15:10:43
//                            $drivers = 'v3_wechat_pay';
//                        } else {
//                            $drivers = 'wechat_pay';
//                        }
//                        /** @var Pay $pay */
//                        $pay = app()->make(Pay::class, [$drivers]);
//                        $pay->refund($no, $refundData);//小程序
                        //小程序退款
                        $ok = MiniProgramService::payOrderRefund($no, $refundData);//小程序
                    break;
                    case PayServices::YUE_PAY:
                        $refundData['refund_price'] = $refundData['price'];
                        if (!$this->yueRefund($refundOrder, $refundData)) {
                            throw new ValidateException('余额退款失败');
                        }
                        $ok = "成功退款！";
                        break;
                }
                $updata = [
                    'id'=>$refundData['id'],
                    'status'=>20,
                    'refund_time'=>time(),
                    'refund_id'=>$refundData['refund_id'],
                ];
                $res = Db::name('car_order_refund')->update($updata);
                Db::name('car_order')->update(['id'=>$order['id'],'status'=>-1,'cancel_time'=>time(),'cancel_refund_price'=>$refundData['price']]);
                if ($res){
                    return $ok;
                    return true;
                }else{
                    throw new ValidateException('退款失败，回写失败');
                }
            }
        });
    }

    /**
     * 余额退款
     * @param $order
     * @param array $refundData
     * @return bool
     */
    public function yueRefund($order, array $refundData){
        /** @var UserServices $userServices */
        $userServices = app()->make(UserServices::class);
        $userMoney = $userServices->value(['uid' => $order['uid']], 'now_money');
        $res = $userServices->bcInc($order['uid'], 'now_money', $refundData['refund_price'], 'uid');
        /** @var UserMoneyServices $userMoneyServices */
        $userMoneyServices = app()->make(UserMoneyServices::class);
        return $res && $userMoneyServices->income('pay_product_refund', $order['uid'], $refundData['refund_price'], bcadd((string)$userMoney, (string)$refundData['refund_price'], 2), $order['id']);

    }

    /**
     * 续租订单退款操作
     * @param $rerent
     * @param array $refundData
     * @param $op_user
     * @param $op_user_type
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function payRerentRefund($rerent, array $refundData,$op_user,$op_user_type)
    {
        return $this->transaction(function () use ($rerent,$refundData,$op_user,$op_user_type){
            $is_occupy = Db::name('car_occupy_time')->where(['order_id'=>$rerent['order_id'],'is_del'=>0])->find();
            //回库存
            if ($is_occupy){
                Db::name('car_occupy_time')->update(['id'=>$is_occupy['id'],'is_del'=>1]);
            }
            //退金额
            if ($refundData['price']>0){
                if (!isset($refundData['refund_id']) || !$refundData['refund_id']){
                    mt_srand();
                    $refundData['refund_id'] = $rerent['rerent_no'].rand(100,900);
                    $refundOrder = $rerent;
                }
                switch ($refundOrder['pay_type']){
                    case PayServices::WEIXIN_PAY:
                        $no = $refundOrder['trade_no'];
                        $refundData['type'] = 'trade_no';
                        $refundData['pay_price'] = $rerent['rerent_price'];
                        $refundData['refund_price'] = $refundData['price'];
                        //小程序退款
                        MiniProgramService::payOrderRefund($no, $refundData);//小程序
                        break;
                    case PayServices::YUE_PAY:
                        $refundData['refund_price'] = $refundData['price'];
                        if (!$this->yueRefund($refundOrder, $refundData)) {
                            throw new ValidateException('余额退款失败');
                        }
                        break;
                }
                $updata = [
                    'id'=>$refundData['id'],
                    'status'=>20,
                    'refund_time'=>time(),
                    'refund_id'=>$refundData['refund_id']
                ];
                $res = Db::name('car_order_refund')->update($updata);
                if ($res){
                    $title = '续租订单【'.$rerent['rerent_no'].'】退款';
                    BaseLogServices::addLog($rerent['order_id'],2,$title,$op_user_type,$op_user['id'],$op_user['user_name'],8);
                    return true;
                }else{
                    throw new ValidateException('退款失败');
                }
            }
        });
    }

    /**
     * 列表
     * @param array $where
     * @param bool $is_page
     * @return array
     */
    public function getList(array $where,bool $is_page = false){
        $page = $limit = 0;
        if($is_page){
            [$page,$limit] = $this->getPageValue();
        }
        $list = $this->dao->getList($where,$page,$limit);
        foreach ($list['list'] as &$item){
            $item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s',$item['add_time']) : '暂无';
            $item['reject_time'] = $item['reject_time'] ? date('Y-m-d H:i:s',$item['reject_time']) : '暂无';
            $item['cancel_time'] = $item['cancel_time'] ? date('Y-m-d H:i:s',$item['cancel_time']) : '暂无';
            $item['refund_time'] = $item['refund_time'] ? date('Y-m-d H:i:s',$item['refund_time']) : '暂无';
            $item['pay_time'] = $item['pay_time'] ? date('Y-m-d H:i:s',$item['pay_time']) : '暂无';
        }
        return $list;
    }
    /**
     * 删除
     * @param int $id
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function delRefund(int $id){
        $city = $this->dao->get($id);
        if ($city) {
            $data['is_del'] = 1;
            $data['delete_time'] = time();
            if (!$this->dao->update($id,$data)) {
                throw new AdminException('删除失败,请稍候再试!');
            }
        }
        return '删除成功!';
    }

    /**
     * 退款申请审核
     * @param $data
     * @param $op_user
     * @param $op_user_type
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function auditRefund($data,$op_user,$op_user_type){
        $refund = CarOrderRefund::find($data['id']);
        $refund = $refund ? $refund->toArray() : [];
        if(!$refund) throw new AdminException('未查询到退款订单信息');
        $order = CarOrder::find($refund['order_id']);
        $order = $order ? $order->toArray() : [];
        if(!$order) throw new AdminException('未查询到订单信息');
        if($data['status'] == -1){
            $update = [
                'status'=>$data['status'],
                'reason'=>$data['reason'],
                'reject_time'=>time()
            ];
            if(CarOrderRefund::where('id',$data['id'])->update($update)){
                $title = '订单【'.$order['order_no'].'】退款申请被驳回';
                BaseLogServices::addLog($order['id'],2,$title,$op_user_type,$op_user['id'],$op_user['user_name'],16);
                return '提交成功';
            }else{
                throw new AdminException('提交失败');
            }
        }elseif($data['status'] == 20){
            if($this->payOrderRefund($order,$refund)){
                $title = '订单【'.$order['order_no'].'】同意退款';
                BaseLogServices::addLog($order['id'],2,$title,$op_user_type,$op_user['id'],$op_user['user_name'],15);
                return '提交成功';
            }else{
                throw new AdminException('提交失败');
            }
        }
    }
}
